// 引入数据库连接
const path = require('path');
const fs = require('fs').promises; // 使用 promise 版本的 fs
// 导入uuid
const { v4: uuidv4 } = require('uuid');
const BASE_UPLOAD_DIR = path.join(__dirname, '../uploads/pdf'); // 项目根下的 uploads/pdf
const { addUserLog } = require("../utils/permission/log.js")

const connection = require('../../config/mysql.js');
const { pdfOutIamges } = require('../utils/runPython.js');
// 创建文件夹并存入数据库
const createFolder = async (ctx) => {
    const { folderName } = ctx.request.body;
    const userId = ctx.tokenObj?.id;
    if (!folderName || !userId) {
        ctx.status = 400;
        ctx.body = { code: 0, msg: '缺少必填字段：folderName 或 token已过期' };
        return;
    }

    // 确保folderName不带有前后的斜杠
    const trimmedFolderName = folderName.trim();
    const folderPath = path.join(BASE_UPLOAD_DIR, trimmedFolderName);

    // 检查文件夹是否已存在
    try {
        await fs.access(folderPath);
        ctx.status = 400;
        ctx.body = { code: 0, msg: '文件夹已存在' };
        return;
    }
    catch (err) {
        // 文件夹不存在，创建文件夹
        await fs.mkdir(folderPath, { recursive: true });
        // 将文件夹信息存入数据库
        const sql = 'INSERT INTO folders (folderName, creationUser) VALUES (?, ?)';
        await connection.query(sql, [trimmedFolderName, userId]);
        await addUserLog(userId, '创建文件夹' + trimmedFolderName);

        ctx.body = { code: 1, msg: '文件夹创建成功' };
    }
}
// 删除文件夹（逻辑删除，重命名文件夹为"原名称（已删除）"，并合并内容）
const deleteFolder = async (ctx) => {
    // 从请求体中获取要删除的文件夹名称和用户身份信息
    const { folderName } = ctx.request.body;
    const userId = ctx.tokenObj?.id;

    // 检查必填字段：folderName 和 userId（token是否有效）
    if (!folderName || !userId) {
        ctx.status = 400;
        ctx.body = { code: 0, msg: '缺少必填字段：folderName 或 token已过期' };
        return;
    }

    // 去除文件夹名称前后的空格
    const trimmedFolderName = folderName.trim();
    // 构建原文件夹的物理路径
    const originalFolderPath = path.join(BASE_UPLOAD_DIR, trimmedFolderName);

    // 定义要添加到文件夹名称的后缀，用于标记已删除的文件夹
    const deletedSuffix = '（已删除）';
    // 构建删除（重命名）后的文件夹名称
    const deletedFolderName = `${trimmedFolderName}${deletedSuffix}`;
    // 构建删除（重命名）后的文件夹的物理路径
    const deletedFolderPath = path.join(BASE_UPLOAD_DIR, deletedFolderName);

    try {
        // 检查原文件夹是否存在
        await fs.access(originalFolderPath);

        // 尝试访问已存在的"已删除"文件夹（即带有"（已删除）"后缀的文件夹）
        try {
            await fs.access(deletedFolderPath);

            // 如果存在同名的"已删除"文件夹，记录日志并准备合并内容
            console.log(`发现已存在的已删除文件夹: ${deletedFolderName}，将合并内容`);

            // 读取原文件夹中的所有文件
            const originalFiles = await fs.readdir(originalFolderPath);

            // 遍历原文件夹中的每个文件
            for (const filename of originalFiles) {
                // 构建原文件的完整物理路径
                const originalFilePath = path.join(originalFolderPath, filename);
                // 构建目标文件夹（已删除文件夹）中的文件完整物理路径
                const deletedFilePath = path.join(deletedFolderPath, filename);

                // 检查目标文件夹中是否已存在同名文件
                if (await fileExists(deletedFilePath)) {
                    // 如果存在同名文件，生成一个新的唯一文件名以避免覆盖
                    const ext = path.extname(filename); // 获取文件扩展名
                    const basename = path.basename(filename, ext); // 获取文件名（不含扩展名）
                    let newFilename = `${basename}_${Date.now()}${ext}`; // 使用时间戳生成新文件名
                    let newFilePath = path.join(deletedFolderPath, newFilename); // 新文件的完整路径

                    // 如果新生成的文件名仍然冲突，继续添加计数器
                    let counter = 1;
                    while (await fileExists(newFilePath)) {
                        newFilename = `${basename}_${Date.now()}_${counter}${ext}`; // 添加计数器
                        newFilePath = path.join(deletedFolderPath, newFilename);
                        counter++;
                    }
                    // 将原文件重命名为新文件名，避免覆盖
                    await fs.rename(originalFilePath, newFilePath);

                    // 构建新文件在数据库中的相对路径（如 /原文件夹名（已删除）/新文件名.pdf）
                    const relativeNewPath = `/${deletedFolderName}/${newFilename}`;

                    // 批量更新将在后续统一处理，此处暂不更新数据库
                } else {
                    // 如果目标文件夹中不存在同名文件，直接移动文件
                    await fs.rename(originalFilePath, deletedFilePath);

                    // 构建新文件在数据库中的相对路径
                    const relativeNewPath = `/${deletedFolderName}/${filename}`;

                    // 批量更新将在后续统一处理，此处暂不更新数据库
                }
            }

            // 所有文件移动完成后，删除原文件夹
            await fs.rm(originalFolderPath, { recursive: true, force: true });

            // 记录日志：已将文件夹内容合并到已存在的已删除文件夹中
            console.log(`已将文件夹 ${trimmedFolderName} 的内容合并到已存在的 ${deletedFolderName} 中，并删除原文件夹`);

        } catch (mergeErr) {
            // 如果访问已删除文件夹失败，检查是否是因为该文件夹不存在
            if (mergeErr.code !== 'ENOENT') throw mergeErr; // 如果不是"文件不存在"的错误，则重新抛出

            // 如果不存在已删除的文件夹，执行正常的重命名和逻辑删除流程

            // 将原文件夹重命名为"原文件夹名（已删除）"
            await fs.rename(originalFolderPath, deletedFolderPath);

            // 记录日志：已将文件夹重命名为已删除文件夹
            console.log(`已将文件夹 ${trimmedFolderName} 重命名为 ${deletedFolderName}`);
        }

        // ======================
        // 批量更新 upload 表
        // ======================
        // 将指定文件夹（trimmedFolderName）下的所有文件记录的 folder 字段置为空字符串 ''，status 设置为 0
        const updateUploadSql = `
            UPDATE \`upload\` 
            SET 
                folder = '', 
                status = 0, 
                updated_at = NOW() 
            WHERE 
                folder = ? AND 
                status = 1
        `;
        // 执行批量更新
        await connection.query(updateUploadSql, [trimmedFolderName]);

        // ======================
        // 删除原文件夹记录
        // ======================
        // 从数据库的 folders 表中删除原文件夹的记录
        await connection.query('DELETE FROM folders WHERE folderName = ?', [trimmedFolderName]);

        // ======================
        // 记录用户操作日志
        // ======================
        // 记录用户操作日志：删除文件夹及其重命名操作
        await addUserLog(userId, `删除文件夹${trimmedFolderName}（已重命名为${deletedFolderName}）`);

        // ======================
        // 返回成功响应
        // ======================
        // 返回成功响应，告知用户文件夹已成功删除并重命名
        ctx.body = {
            code: 1,
            msg: `文件夹"${trimmedFolderName}"已成功删除（重命名为"${deletedFolderName}"）并合并到已删除文件夹中`
        };

    } catch (err) {
        // 捕获并处理任何在删除过程中发生的错误
        console.error('删除文件夹时出错：', err);

        // 如果错误是因为文件夹不存在（错误码为 'ENOENT'），返回文件夹不存在的错误信息
        if (err.code === 'ENOENT') {
            ctx.status = 400;
            ctx.body = { code: 0, msg: '文件夹不存在' };
        } else {
            // 其他错误，返回500服务器错误，并附带错误信息
            ctx.status = 500;
            ctx.body = { code: 0, msg: '删除文件夹失败', error: err.message };
        }
    }
};

// 辅助函数：检查指定路径的文件或文件夹是否存在
function fileExists(filePath) {
    return fs.access(filePath).then(() => true).catch(() => false);
}

// 获取文件夹列表
const getFolderList = async (ctx) => {
    try {
        const sql = 'SELECT * FROM folders ORDER BY creationUser, id DESC';
        const [rows] = await connection.query(sql);
        ctx.body = { code: 1, data: rows, msg: '获取文件夹列表成功' };
    } catch (err) {
        console.error('获取文件夹列表失败：', err);
        ctx.status = 500;
        ctx.body = { code: 500, msg: err.message, data: null };
    }
}

// 获取对应文件夹下的文件列表（带分页）
const getFileList = async (ctx) => {
    try {
        const { folderName, page = 1, pageSize = 10 } = ctx.query;

        // 参数验证
        if (!folderName) {
            ctx.status = 400;
            ctx.body = { code: 0, msg: '缺少必填参数：folderName' };
            return;
        }

        // 转换为数字类型，设置默认值和边界
        const pageNum = Math.max(1, parseInt(page) || 1);
        const sizeNum = Math.min(Math.max(1, parseInt(pageSize) || 10), 100); // 限制最大每页100条

        // 计算偏移量
        const offset = (pageNum - 1) * sizeNum;

        // 先查询总数
        const countSql = `SELECT COUNT(*) as total FROM \`${'upload'}\` WHERE folder = ? AND status = 1`;
        const [countResult] = await connection.query(countSql, [folderName]);
        const total = countResult[0]?.total || 0;

        // 再查询分页数据 - 建议按创建时间倒序排列
        const dataSql = `
            SELECT * FROM \`upload\` 
            WHERE folder = ? AND status = 1 
            ORDER BY created_at DESC 
            LIMIT ? OFFSET ?
        `;

        const [rows] = await connection.query(dataSql, [folderName, sizeNum, offset]);

        // 计算总页数
        const totalPages = Math.ceil(total / sizeNum);

        ctx.body = {
            code: 1,
            data: {
                files: rows,
                pagination: {
                    currentPage: pageNum,
                    pageSize: sizeNum,
                    total: total,
                    totalPages: totalPages,
                    hasNextPage: pageNum < totalPages,
                    hasPrevPage: pageNum > 1
                }
            }
        };
    } catch (err) {
        console.error('获取文件列表失败：', err);
        ctx.status = 500;
        ctx.body = { code: 0, msg: '获取文件列表失败' };
    }
}

// 文件上传接口
const uploadPdf = async (ctx) => {
    try {
        const files = ctx.request.files;
        const userId = ctx.tokenObj?.id;
        const formData = ctx.request.body;
        // ====== 只允许单个文件上传 ======
        // 原 ctx.request.files.files 可能是单文件或数组，这里强制取第一个，只处理单个文件
        const fileArray = files.files ? (Array.isArray(files.files) ? files.files : [files.files]) : [];
        const file = fileArray[0]; // 只处理第一个（单文件）

        if (!file || !file.filepath || !file.originalFilename) {
            ctx.status = 400;
            ctx.body = { code: 0, msg: '未上传有效文件' };
            return;
        }

        const originalname = file.originalFilename.split('/').pop(); // 前端上传的原始文件名，如 "合同.pdf"

        const filename = file.newFilename || file.originalFilename || 'file-' + Date.now(); // 原始名或新名
        const oldFilePath = file.filepath; // 临时文件路径

        let folder = formData.folder?.trim() || '';
        const fileFolder = folder ? `/${folder}/` : '/';
        const targetFolder = path.join(BASE_UPLOAD_DIR, folder);

        const fileExt = filename.split('.').pop()?.toLowerCase(); // 如 pdf
        const fileId = uuidv4(); // 唯一ID，如 550e8400-e29b-41d4-a716-446655440000
        const uuidFilename = `${fileId}${fileExt ? `.${fileExt}` : ''}`; // 如 550e8400-e29b-41d4-a716-446655440000.pdf

        // 确保目标目录存在
        await fs.mkdir(targetFolder, { recursive: true });

        // 移动临时文件到正式路径（使用 uuid 文件名）
        const targetFilePath = path.join(targetFolder, uuidFilename);
        await fs.rename(oldFilePath, targetFilePath);

        // 获取文件信息
        const stats = await fs.stat(targetFilePath);
        const filesize = stats.size;
        const mimetype = file.mimetype || 'application/octet-stream';

        // 清理 folder 格式，避免前后有多余斜杠
        const cleanFolder = fileFolder.replace(/\/+$/, '').replace(/^\/+/, '');

        // 构造将要存入数据库的文件对象（先构造好，后面直接插入）
        const fileData = {
            id: fileId,
            user_id: userId,
            filename: originalname,         // 展示用的原始文件名，如 "合同.pdf"
            path: `/pdf${fileFolder}${uuidFilename}`, // 对外访问路径，带 uuid 文件名
            size: filesize,
            mime_type: mimetype,
            file_ext: fileExt || null,      // 如 "pdf"
            created_at: new Date(),
            updated_at: new Date(),
            status: 1,
            description: formData.description || null,
            download_count: 0,
            folder: cleanFolder
        };

        // ====== 验重：检查是否已存在相同 folder + filename 且 status = 1 的记录 ======
        const checkSql = `
            SELECT COUNT(*) AS count
            FROM \`upload\`
            WHERE folder = ? AND filename = ? AND status = 1
        `;
        const [rows] = await connection.query(checkSql, [fileData.folder, fileData.filename]);

        const isDuplicate = rows[0].count > 0;

        if (isDuplicate) {
            ctx.status = 200;
            ctx.body = { code: 2, msg: '文件已存在' };
            return; // 直接拦截，不存数据库、不保留文件
        }

        // ====== 验重通过，存入数据库 ======
        const insertSql = `
            INSERT INTO \`upload\`
            (id, user_id, filename, path, size, mime_type, file_ext, created_at, updated_at, status, description, download_count, folder)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        `;

        const insertValues = [
            fileData.id,
            fileData.user_id,
            fileData.filename,
            fileData.path,
            fileData.size,
            fileData.mime_type,
            fileData.file_ext,
            fileData.created_at,
            fileData.updated_at,
            fileData.status,
            fileData.description,
            fileData.download_count,
            fileData.folder
        ];

        await connection.query(insertSql, insertValues);

        // ====== 返回成功响应 ======
        ctx.status = 200;
        ctx.body = {
            code: 1,
            msg: '文件上传成功',
            data: {
                files: [{
                    id: fileData.id,
                    filename: fileData.filename,       // 原始文件名（展示用）
                    size: fileData.size,
                    path: fileData.path,               // 带 uuid 的访问路径
                    folder: fileData.folder,
                    downloadUrl: `/download/${fileData.id}`, // 按 id 下载
                }]
            }
        };

    } catch (error) {
        console.error('文件上传失败：', error);
        ctx.status = 500;
        ctx.body = {
            code: 0,
            msg: '文件上传失败',
            error: error.message,
        };
    }
};
// 处理文件夹
const runPyForPdfToImg = async (ctx) => {
    // 1. 从请求体中获取参数，比如 { folder: 'cell' }
    const { folder } = ctx.request.body;

    if (!folder) {
        ctx.status = 400;
        ctx.body = {
            code: 0,
            msg: '缺少参数：folder（PDF文件夹名称，如 cell）'
        };
        return;
    }

    try {
        console.log(`🔧 开始处理文件夹: ${folder}`);

        // 2. 调用 PDF 处理函数，等待其执行完成（异步阻塞，直到 Python 脚本运行结束）
        const result = await pdfOutIamges(folder);

        // 3. 构造返回给前端的结构
        ctx.body = {
            code: 1,
            msg: 'PDF 图片提取完成',
            data: result // 包含 status, total_files, success_count, ...
        };

    } catch (error) {
        console.error('❌ 处理 PDF 时发生错误:', error.message);

        ctx.status = 500;
        ctx.body = {
            code: 0,
            msg: '处理 PDF 失败',
            error: error.message
        };
    }
}

// 获取某个文件夹下的图片列表（支持分页）仅查询 status 大于等于0的图片
const getImgList = async (ctx) => {
    const { folder, page = 1, pageSize = 10 } = ctx.query;

    if (!folder) {
        ctx.status = 400;
        ctx.body = {
            code: 0,
            msg: '缺少参数：folder（如：cell）'
        };
        return;
    }

    // 转换为数字，设置默认值和范围保护
    const pageNum = Math.max(1, parseInt(page, 10) || 1);
    const sizeNum = Math.max(1, parseInt(pageSize, 10) || 10);

    try {
        // 1. 查询该 folder 下的总记录数
        const [countResult] = await connection.query(
            'SELECT COUNT(*) AS total FROM images WHERE folder_key = ? AND status > 0',
            [folder]
        );

        const total = countResult[0].total;
        const totalPages = Math.ceil(total / sizeNum);

        // 2. 查询当前页的图片数据（分页）
        const offset = (pageNum - 1) * sizeNum;

        const [rows] = await connection.query(
            `
            SELECT 
                id,
                pdf_uuid,
                folder_key,
                image_size,
                image_path,
                status,
                data_time
            FROM images 
            WHERE folder_key = ?
            AND status > 0
            ORDER BY data_time DESC
            LIMIT ? OFFSET ?
            `,
            [folder, sizeNum, offset]
        );

        // 3. 格式化返回的图片数据
        const imageList = rows.map(row => ({
            id: row.id,
            pdfName: row.pdf_uuid,
            imageName: path.basename(row.image_path),
            imagePath: row.image_path,
            imageSize: row.image_size,
            status: row.status,
            createdAt: row.data_time,
            folder_key: row.folder_key
        }));

        // 4. 返回最终结果
        ctx.body = {
            code: 1,
            msg: '查询成功',
            data: {
                folder,
                page: pageNum,
                pageSize: sizeNum,
                total,
                totalPages,
                images: imageList
            }
        };

    } catch (error) {
        console.error('❌ 查询图片列表失败:', error.message);
        ctx.status = 500;
        ctx.body = {
            code: 0,
            msg: '查询图片列表失败',
            error: error.message
        };
    }
};

// 修改图片状态
const changeImgStatus = async (ctx) => {
    const { id, status } = ctx.request.body;

    // 1. 参数校验
    if (!id) {
        ctx.status = 400;
        ctx.body = {
            code: 0, // 统一：0表示失败
            msg: '缺少参数：id（图片ID）'
        };
        return;
    }

    // 验证 status
    if (status === undefined || status === null) {
        ctx.status = 400;
        ctx.body = { code: 0, msg: '缺少参数：status（状态）' };
        return;
    }

    try {
        // 2. 业务限制：如果状态要设置为 0（比如删除/取消），需要检查是否已标注
         if (status === 0) {
            // 检查该图片是否已被标注：multi_label 表中是否存在对应的 imageUrl
            const [annotationRows] = await connection.query(
                'SELECT * FROM multi_label WHERE imageUrl = (SELECT image_path FROM images WHERE id = ?)',
                [id]
            );

            if (annotationRows.length > 0) {
                ctx.status = 200;
                ctx.body = {
                    code: 0,
                    msg: '该图片已经被标注过，不能执行删除操作，请先清除标注'
                };
                return;
            }
        }

        // 3. 更新主表：images 的状态
        const [updateResult] = await connection.query(
            'UPDATE images SET status = ? WHERE id = ?',
            [status, id]
        );

        // 4. 如果没有影响到任何行，说明图片不存在
        if (updateResult.affectedRows === 0) {
            ctx.status = 404;
            ctx.body = {
                code: 0,
                msg: '图片未找到'
            };
            return;
        }

        // 5. 如果状态设置为 0，同步更新 multi_label 表中关联记录的 state 为 0
        if (status === 0) {
            await connection.query(
                'UPDATE multi_label SET state = 0 WHERE imageUrl = (SELECT image_path FROM images WHERE id = ?)',
                [id]
            );
        }

        // 6. 返回成功响应
        ctx.status = 200;
        ctx.body = {
            code: 1, // 统一：1表示成功
            msg: '图片状态更新成功'
        };

    } catch (error) {
        console.error('❌ 更新图片状态失败:', error.message);
        ctx.status = 500;
        ctx.body = {
            code: 0,
            msg: '服务器错误，更新图片状态失败',
            error: process.env.NODE_ENV === 'development' ? error.message : undefined
        };
    }
};
module.exports = { createFolder, deleteFolder, getFolderList, getFileList, uploadPdf, runPyForPdfToImg, getImgList, changeImgStatus };